﻿/*
 * Created by SharpDevelop.
 * User: Matjaz
 * Date: 5.11.2007
 * Time: 22:41
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */

using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing.Printing;
using System.IO;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Microsoft.Win32;

namespace gopher
{	
	/// <summary>
	/// Description of MainForm.
	/// </summary>
	public partial class MainForm : Form
	{
		//table of items
		public List<int> indexList = new List<int>();
		public List<string> infoList = new List<string>();
		public List<string> descList = new List<string>();
		public List<string> selectList = new List<string>();
		public List<string> addressList = new List<string>();
		public List<string> portList = new List<string>();
		//search
		public string iskanje = "";
		//socket timeout
		public int iTimeout = 500;
		//history
		public List<int> indexHist = new List<int>();
		public List<string> descHist = new List<string>();
		public List<string> selectHist = new List<string>();
		public List<string> addressHist = new List<string>();
		public List<string> portHist = new List<string>();
        //printing
        private PrintDocument printDoc = new PrintDocument();
        public StringBuilder printSB = new StringBuilder();
        private printersupport _printdocument = new printersupport();

		public MainForm()
		{
			//
			// The InitializeComponent() call is required for Windows Forms designer support.
			//
			InitializeComponent();
		}
		
		static string ReadLine (Stream s)
		{
			List<byte> lineBuffer = new List<byte>();
			while (true)
			{
				int b = s.ReadByte();
				if (b == 10 || b < 0) break;
				if (b != 13) lineBuffer.Add ((byte)b);
			}
			//return Encoding.UTF8.GetString (lineBuffer.ToArray());
			return Encoding.ASCII.GetString (lineBuffer.ToArray());
		}

		static void SendCommand (Stream stream, string line)
		{
			try
			{
				//byte[] data = Encoding.UTF8.GetBytes (line + "\r\n");
				byte[] data = Encoding.ASCII.GetBytes (line + "\r\n");
				stream.Write (data, 0, data.Length);
			}
			catch (Exception e)
			{
				System.Windows.Forms.MessageBox.Show("Error sending data to the network.\r\n\r\n"+e.Message, "Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
			}
		}
		
		void Pocisti()
		{
			for (int i = gopherMenu.Items.Count; i > 0; i--)
			{
				gopherMenu.Items.RemoveAt(0);
			}
			indexList.Clear();
			infoList.Clear();
			descList.Clear();
			selectList.Clear();
			addressList.Clear();
			portList.Clear();
            printSB.Remove(0, printSB.Length);
		}
		
		void PocistiZgodovino()
		{
			for (int i = historyButton.DropDownItems.Count; i > 0; i--)
			{
				historyButton.DropDownItems.RemoveAt(0);
			}
//			indexHist.Clear();
//			infoHist.Clear();
//			descHist.Clear();
//			selectHist.Clear();
//			addressHist.Clear();
//			portHist.Clear();
		}
		
		void ToolStripButton2Click(object sender, EventArgs e)
		{
			Pocisti();
		}
		
		void ExitToolStripMenuItemClick(object sender, EventArgs e)
		{
			this.Close();
		}
		
		void DobiImenik(string selektor, string streznik, string vrata)
		{
			int iPort=7070;
			Pocisti();
			try
			{
				iPort = Convert.ToInt32(vrata);
			}
			catch (Exception ex)
			{
				System.Windows.Forms.MessageBox.Show("It seems that the 'port' number is wrong - it is not a number or it is out of range 0-65535\r\n\r\n"+ex.Message, "Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
			}
			try
			{
				TcpClient client = new TcpClient (streznik, iPort);
				NetworkStream n = client.GetStream();
				
				SendCommand (n, selektor);
				List<string> imenik = new List<string>();
				if (n.DataAvailable == false) Thread.Sleep(iTimeout);
				while (n.DataAvailable)
				{
					string line = ReadLine (n);             // e.g.  "1Streznik seanm.ca              seanm.ca        70"
					if (line == ".") break;					// end of server output. we ignore anything past "." alone on the line
					imenik.Add(line);						// add line to list of lines
					if (n.DataAvailable == false) Thread.Sleep(iTimeout);
				}
				int i = 0;
				foreach (string vrstica in imenik)
				{
					string sTemp = vrstica;
					if (sTemp.Contains("\t"))
					{
						char[] charSeparators = new char[] {'\t'};
						indexList.Add(i);
						infoList.Add(sTemp.Split(charSeparators, System.StringSplitOptions.None)[0].ToCharArray()[0].ToString());
						descList.Add(sTemp.Split(charSeparators, System.StringSplitOptions.None)[0].Substring(1,sTemp.Split(charSeparators, System.StringSplitOptions.None)[0].Length-1));
						selectList.Add(sTemp.Split(charSeparators, System.StringSplitOptions.None)[1]);
						addressList.Add(sTemp.Split(charSeparators, System.StringSplitOptions.None)[2]);
						portList.Add(sTemp.Split(charSeparators, System.StringSplitOptions.None)[3]);
					}
					else
					{
						indexList.Add(i);
						infoList.Add("3");
						descList.Add(sTemp.Substring(1));
						selectList.Add("");
						addressList.Add("");
						portList.Add("");
					}
					i++;
				}
				foreach (int myItem in indexList)
				{
#region items
					StringBuilder SBPredmet = new StringBuilder();
					if (infoList[myItem] == "i")
					{
						SBPredmet.Append("[inf] ");
					}
					else if (infoList[myItem] == "0")
					{
						SBPredmet.Append("[fil] ");
					}
					else if (infoList[myItem] == "1")
					{
						SBPredmet.Append("[dir] ");
					}
					else if (infoList[myItem] == "2")
					{
						SBPredmet.Append("[CSO] ");
					}
					else if (infoList[myItem] == "3")
					{
						SBPredmet.Append("[ERR] ");
					}
					else if (infoList[myItem] == "4")
					{
						SBPredmet.Append("[HEX] ");
					}
					else if (infoList[myItem] == "5")
					{
						SBPredmet.Append("[DOS] ");
					}
					else if (infoList[myItem] == "6")
					{
						SBPredmet.Append("[UUE] ");
					}
					else if (infoList[myItem] == "7")
					{
						SBPredmet.Append("[ ? ] ");
					}
					else if (infoList[myItem] == "8")
					{
						SBPredmet.Append("[ T ] ");
					}
					else if (infoList[myItem] == "9")
					{
						SBPredmet.Append("[bin] ");
					}
					else if (infoList[myItem] == "+")
					{
						SBPredmet.Append("[ds+] ");
					}
					else if (infoList[myItem] == "g")
					{
						SBPredmet.Append("[gif] ");
					}
					else if (infoList[myItem] == "h")
					{
						SBPredmet.Append("[htm] ");
					}
					else if (infoList[myItem] == "I")
					{
						SBPredmet.Append("[IMG] ");
					}
					else if (infoList[myItem] == "T")
					{
						SBPredmet.Append("[TN3] ");
					}
					else if (infoList[myItem] == "P")
					{
						SBPredmet.Append("[pdf] ");
					}
					else if (infoList[myItem] == "d")
					{
						SBPredmet.Append("[pdf] ");
					}
					else if (infoList[myItem] == "s")
					{
						SBPredmet.Append("[snd] ");
					}
					else
					{
						SBPredmet.Append("["+infoList[myItem]+"  ] ");
					}
					gopherMenu.Items.Add(SBPredmet.ToString()+descList[myItem]);
                    printSB.AppendLine(descList[myItem]);
#endregion
				}
			}
			catch (Exception e)
			{
				System.Windows.Forms.MessageBox.Show("Unable to establish connection\r\n\r\n"+e.Message, "Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
			}
			
			PocistiZgodovino();
			foreach (string Zgodovina in descHist)
			{
				historyButton.DropDownItems.Add(Zgodovina);
			}
			DodajStatus(selektor, streznik, vrata);
		}
		
		void ToolStripButton4Click(object sender, EventArgs e)
		{
			Pocisti();
			DodajZgodovino(selectorBox.Text, selectorBox.Text, serverBox.Text, portBox.Text);
			DobiImenik(selectorBox.Text, serverBox.Text, portBox.Text);
		}
		
		void ToolStripButton7Click(object sender, EventArgs e)
		{
			try
			{
				System.Windows.Forms.MessageBox.Show("Index: "+indexList[gopherMenu.SelectedIndex]+"\n"+
				                                     "Info ID: "+infoList[gopherMenu.SelectedIndex]+"\n"+
				                                     "Descriptor: "+descList[gopherMenu.SelectedIndex]+"\n"+
				                                     "Selector: "+selectList[gopherMenu.SelectedIndex]+"\n"+
				                                     "Server: "+addressList[gopherMenu.SelectedIndex]+"\n"+
				                                     "Port: "+portList[gopherMenu.SelectedIndex],
				                                     descList[gopherMenu.SelectedIndex], System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information);
			}
			catch (Exception InfoE)
			{
				System.Windows.Forms.MessageBox.Show("Before clicking Info button, you need to get the menu from the server\r\n\r\n"+InfoE.Message, "Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
			}
		}
		
		void gopherMenuDoubleClick(object sender, EventArgs e)
		{
			try
			{
				if (infoList[gopherMenu.SelectedIndex] == "1")
				{
					//imenik
					selectorBox.Text = selectList[gopherMenu.SelectedIndex];
					serverBox.Text = addressList[gopherMenu.SelectedIndex];
					portBox.Text = portList[gopherMenu.SelectedIndex];
					DodajZgodovino(descList[gopherMenu.SelectedIndex], selectList[gopherMenu.SelectedIndex], addressList[gopherMenu.SelectedIndex], portList[gopherMenu.SelectedIndex]);
					DobiImenik(selectList[gopherMenu.SelectedIndex], addressList[gopherMenu.SelectedIndex], portList[gopherMenu.SelectedIndex]);
				}
				else if (infoList[gopherMenu.SelectedIndex] == "0")
				{
					//tekstovna datoteka
					TekstovnoOkno tekstOkno = new TekstovnoOkno(selectList[gopherMenu.SelectedIndex], addressList[gopherMenu.SelectedIndex], portList[gopherMenu.SelectedIndex], iTimeout);
					tekstOkno.ShowInTaskbar = false;
					tekstOkno.ShowDialog();
				}
				else if (infoList[gopherMenu.SelectedIndex] == "7")
				{
					//iskanje po strežniku
					iskanjePoStrezniku search = new iskanjePoStrezniku();
					if (search.ShowDialog() == DialogResult.OK)
					{
						DodajZgodovino(descList[gopherMenu.SelectedIndex]+" ("+search.iskanje+")", selectList[gopherMenu.SelectedIndex]+"\t"+search.iskanje, addressList[gopherMenu.SelectedIndex], portList[gopherMenu.SelectedIndex]);
						DobiImenik(selectList[gopherMenu.SelectedIndex]+"\t"+search.iskanje, addressList[gopherMenu.SelectedIndex], portList[gopherMenu.SelectedIndex]);
					}
				}
				else if (infoList[gopherMenu.SelectedIndex] == "i")
				{
					//ne naredimo nič - informacije
				}
				else if (infoList[gopherMenu.SelectedIndex] == "3")
				{
					//ne naredimo nič - napaka
				}
				else if (infoList[gopherMenu.SelectedIndex] == "8")
				{
					//telnet
					System.Diagnostics.Process.Start("telnet.exe", addressList[gopherMenu.SelectedIndex]+" "+portList[gopherMenu.SelectedIndex]);
				}
				else if (infoList[gopherMenu.SelectedIndex] == "2")
				{
					//Telefonski imenik
					ImenikOkno imenik = new ImenikOkno(selectList[gopherMenu.SelectedIndex], addressList[gopherMenu.SelectedIndex], portList[gopherMenu.SelectedIndex], iTimeout);
					imenik.Show();
				}
				else
				{
					DolPotegniPredmet();
				}
			}
			catch (Exception ex)
			{
				System.Windows.Forms.MessageBox.Show("Before clicking the menu, you need to get it from the server\r\n\r\n"+ex.Message, "Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
			}
		}
		
		void ToolStripButton1Click(object sender, EventArgs e)
		{
		try
			{
				if (infoList[gopherMenu.SelectedIndex] == "3") {}
				else if (infoList[gopherMenu.SelectedIndex] == "i") {}
				else
				{
					DolPotegniPredmet();
				}
				
			}
			catch (Exception dolpotegE)
			{
				System.Windows.Forms.MessageBox.Show("Before pressing this button, you need to get a menu from the server\r\n\r\n"+dolpotegE.Message, "Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
			}
		}
		
		void dolpotegNit(string selektor, string streznik, string vrata)
		{
			Dolpoteg DownloadWindow = new Dolpoteg(selektor, streznik, vrata);
			DownloadWindow.ShowInTaskbar = false;
			DownloadWindow.ShowDialog();
			return;
		}
		
		void DolPotegniPredmet()
		{
			ThreadContainer threadcontainer = new ThreadContainer(selectList[gopherMenu.SelectedIndex], addressList[gopherMenu.SelectedIndex], portList[gopherMenu.SelectedIndex]);
			Thread DownloadThread = new Thread(new ThreadStart(threadcontainer.ThreadFunction));
			
			DownloadThread.Start();
		}
		
		void gopherMenuKeyDown(object sender, KeyEventArgs e)
		{
			if (e.KeyCode == Keys.Enter)
			{
				gopherMenuDoubleClick(sender, e);
			}
		}
		
		void AboutToolStripMenuItemClick(object sender, EventArgs e)
		{
			oProgramu aboutBox = new oProgramu();
			aboutBox.ShowDialog();
		}
		
		void DodajZgodovino(string deskriptor, string selektor, string streznik, string vrata)
		{
			if (deskriptor.Trim()=="")
			{
				descHist.Add("Title Page");
			}
			else
			{
				descHist.Add(deskriptor);
			}			
			selectHist.Add(selektor);
			addressHist.Add(streznik);
			portHist.Add(vrata);
		}
		
		void DodajStatus(string selektor, string streznik, string vrata)
		{
			selectorBox.Text = selektor;
			serverBox.Text = streznik;
			portBox.Text = vrata;
		}
		
		void ToolStripDropDownButton1DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
		{
			Pocisti();
			int mojIndex = historyButton.DropDownItems.IndexOf(e.ClickedItem);
			DobiImenik(selectHist[mojIndex], addressHist[mojIndex], portHist[mojIndex]);
		}
		
		void ContentsToolStripMenuItemClick(object sender, EventArgs e)
		{
			Help.ShowHelp(this, Application.ExecutablePath.Substring(0, Application.ExecutablePath.LastIndexOf("\\"))+"\\Help\\gopher.chm", "html\\index.htm");
			//Help.ShowHelp(this, Application.ExecutablePath.Substring(0, Application.ExecutablePath.LastIndexOf("\\"))+"\\Help\\gopher1.chm", "html\\2text-window.htm");
			//Help.ShowHelpIndex(this, Application.ExecutablePath.Substring(0, Application.ExecutablePath.LastIndexOf("\\"))+"\\Help\\gopher1.chm");
		}
		
        private void printToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PrintDialog pd = new PrintDialog();
            _printdocument.Text = printSB.ToString();
            _printdocument.Font = gopherMenu.Font;
            pd.Document = _printdocument;
            if (pd.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    _printdocument.Print();
                }
                catch (Exception printException)
                {
                    System.Windows.Forms.MessageBox.Show("Printing error.\r\n\r\n" + printException.Message, "Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
                }
            }
        }

        private void pripravaStraniToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PageSetupDialog psd = new PageSetupDialog();
            psd.Document = _printdocument;
            psd.ShowDialog();
        }

        private void printPreviewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PrintPreviewDialog ppd = new PrintPreviewDialog();
            _printdocument.Text = printSB.ToString();
            _printdocument.Font = gopherMenu.Font;
            ppd.Document = _printdocument;
            ppd.ShowDialog();
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveDialog = new SaveFileDialog();
            saveDialog.Filter = ("Text file (*.txt)|*.txt|All files (*.*)|*.*");
            if (saveDialog.ShowDialog() == DialogResult.OK)
            {
                StreamWriter sw = new StreamWriter(saveDialog.FileName);
                sw.Write(printSB.ToString());
                sw.Close();
            }
        }
		
		void ToolStripButton3Click(object sender, EventArgs e)
		{
			printToolStripMenuItem_Click(sender,e);
		}		
		
		void CustomizeToolStripMenuItemClick(object sender, EventArgs e)
		{
			SettingsDialog settingsDialog = new SettingsDialog();
			settingsDialog.Show();
		}
		
		void MainFormLoad(object sender, EventArgs e)
		{
			string settingsFile;
			RegistryKey key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders");
			settingsFile = key.GetValue("AppData").ToString()+"\\Gopher\\settings.xml";
//			System.Windows.Forms.MessageBox.Show(settingsFile, "Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
//			
//			settingsFile = Assembly.GetExecutingAssembly().Location;
//			settingsFile = settingsFile.Substring(0,settingsFile.LastIndexOf("\\"));
//			settingsFile = settingsFile+"\\settings.xml";
			try
			{
				DataSet ds = new DataSet();
				ds.ReadXml(settingsFile);
				DataRow dr = ds.Tables[0].Rows[0];
				serverBox.Text = dr["server"].ToString();
				selectorBox.Text = dr["selector"].ToString();
				portBox.Text = dr["port"].ToString();
				iTimeout = Convert.ToInt32(dr["timeout"].ToString());
			}
			catch(Exception emoja)
			{
				MessageBox.Show(emoja.Message);
				SettingsDialog settingsDialog = new SettingsDialog();
				settingsDialog.Show();
			}
		}
		
		void GopherMenuSelectedIndexChanged(object sender, EventArgs e)
		{
			try
			{
				Status.Text = ("Item ID: "+infoList[gopherMenu.SelectedIndex]+" - "+				                                     
				                                     "Selector: "+selectList[gopherMenu.SelectedIndex]+" - "+
				                                     "Server: "+addressList[gopherMenu.SelectedIndex]+" - "+
				                                     "Port: "+portList[gopherMenu.SelectedIndex]);
			}
			catch (Exception)
			{

			}
		}
		
		void MainFormHelpRequested(object sender, HelpEventArgs hlpevent)
		{
			Help.ShowHelp(this, Application.ExecutablePath.Substring(0, Application.ExecutablePath.LastIndexOf("\\"))+"\\Help\\gopher.chm", "html\\main-window.htm");
		}
	}
	
	class ThreadContainer
	{
		string intMyx;
		string intMyy;
		string intMyz;

		public ThreadContainer(string intX, string intY, string intZ)
		{
			intMyx = intX;
			intMyy = intY;
			intMyz = intZ;
		}

		public void ThreadFunction()
		{
			Dolpoteg DownloadWindow = new Dolpoteg(intMyx, intMyy, intMyz);
			DownloadWindow.ShowInTaskbar = false;
			DownloadWindow.ShowDialog();
		}
	}
	
}
